package club.sanmubird.wechatdemo.controller;

import club.sanmubird.wechatdemo.bean.AccessToken;
import club.sanmubird.wechatdemo.util.NetWorkUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Random;

/**
 * @author Sam
 */
@Controller
@RequestMapping("/wechat")
@Slf4j
public class WeChatController extends BaseController {
	private static final String TOKEN = "sam";
	private static final String REDIRECT_URL = "redirectUrl";
	/**
	 * 提前时间
	 */
	private static final int ADVANCE_EXPIRE = 200;
	private static final int THOUSAND_TIMES = 1000;
	private String baseAccessToken;
	private Long nextExpireTimeStamp = System.currentTimeMillis();

	@Value("${wechat.appId}")
	private String appId;
	@Value("${wechat.appSecret}")
	private String appSecret;
	@Value("${wechat.accessTokenUrl}")
	private String accessTokenUrl;

	@Value("${wechat.snsapiBaseUrl}")
	private String snsapiBaseUrl;
	@Value("${wechat.authAccessTokenUrl}")
	private String authAccessTokenUrl;
	@Value("${wechat.userInfoUrl}")
	private String userInfoUrl;

	@Value("${wechat.redirectUserInfoUrl}")
	private String redirectUserInfoUrl;

	@RequestMapping("/createUrl")
	@ResponseBody
	private String createUrl(HttpServletRequest request, HttpServletResponse response) {
		String redirectUrl = request.getParameter(REDIRECT_URL);
		Cookie cookie = new Cookie(REDIRECT_URL, redirectUrl);
		cookie.setSecure(true);
		response.addCookie(cookie);
		int i = new Random().nextInt(10);
		return String.format(snsapiBaseUrl, i);
	}

	@RequestMapping("/getUserInfo")
	private String getUserInfo(HttpServletRequest request, RedirectAttributes attr) {
		getBaseAccessToken();
		String tokenUrl = String.format(authAccessTokenUrl, request.getParameter("code"));
		String tokenResult = NetWorkUtil.getHttpsResponse(tokenUrl, "");
		JSONObject jsonObject = JSON.parseObject(tokenResult);
		String openid = jsonObject.getString("openid");
		String userUrl = String.format(userInfoUrl, baseAccessToken, openid);
		String userInfoStr = NetWorkUtil.getHttpsResponse(userUrl, "");
		attr.addAttribute("userInfoStr", userInfoStr);
		String redirectUrl = "http://d2h238.natappfree.cc/login/backWxLogin";
		return "redirect:" + redirectUrl;
	}

	@RequestMapping("/getUserInoByOpenId")
	@ResponseBody
	private String getUserInoByOpenId(HttpServletRequest request, String openId) {
		getBaseAccessToken();
		String userUrl = String.format(userInfoUrl, baseAccessToken, openId);
		return NetWorkUtil.getHttpsResponse(userUrl, "");
	}


	@RequestMapping("/createUserInfoUrl")
	@ResponseBody
	private String createUserInfoUrl(HttpServletRequest request) {
		int i = new Random().nextInt(10);
		return String.format(redirectUserInfoUrl, i);
	}

	@RequestMapping("/demo")
	public void demo(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		log.info("-----开始校验签名-----");

		// 接收微信服务器发送请求时传递过来的参数
		String signature = req.getParameter("signature");
		String timestamp = req.getParameter("timestamp");
		//随机数
		String nonce = req.getParameter("nonce");
		//随机字符串
		String echostr = req.getParameter("echostr");

		// 将token、timestamp、nonce三个参数进行字典序排序  并拼接为一个字符串
		String sortStr = sort(TOKEN, timestamp, nonce);
		// 字符串进行shal加密
		String mySignature = shal(sortStr);
		// 校验微信服务器传递过来的签名 和  加密后的字符串是否一致, 若一致则签名通过
		if (!"".equals(signature) && !"".equals(mySignature) && signature.equals(mySignature)) {
			log.info("-----签名校验通过-----");
			resp.getWriter().write(echostr);
		} else {
			log.info("-----校验签名失败-----");
		}
	}

	@RequestMapping("/getAccessToken")
	@ResponseBody
	private String getAccessToken() {
		getBaseAccessToken();
		return baseAccessToken;
	}

	private void getBaseAccessToken() {
		long currentTimeMillis = System.currentTimeMillis();
		// 如果 当前时间 小于 下次过期时间 则 直接取 当前的 baseAccessToken 否则重新发送请求。
		if (currentTimeMillis >= nextExpireTimeStamp) {
			String result = NetWorkUtil.getHttpsResponse(accessTokenUrl, "");
			AccessToken accessToken = JSON.parseObject(result, AccessToken.class);
			baseAccessToken = accessToken.getAccess_token();
			nextExpireTimeStamp = System.currentTimeMillis() + (accessToken.getExpires_in() - ADVANCE_EXPIRE) * THOUSAND_TIMES;
		}
		log.info("获取到的access_token=" + baseAccessToken);
	}

}
